﻿// <copyright file="PendingChangesControl.xaml.cs" company="Soumya Chattopadhyay">
// Copyright (c) 2010 All Right Reserved
// </copyright>
// <disclaimer> This software is intented for educational purposes only and not for 
// commerical or prodution use. The software is provided "as is", without warranty 
// of any kind, express or implied, including but not limited to the warranties of 
// merchantability, fitness for a particular purpose and noninfringement. In no event 
// shall the author(s) or copyright holder(s) be liable for any claim, damages or other 
// liability, whether in an action of contract, tort or otherwise, arising from, out of 
// or in connection with the software or the use or other dealings in the software.
// </disclaimer>

namespace My.CodePlex.TFSExplorer
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Text;
    using System.Threading;
    using System.Windows.Controls;
    using System.Windows.Media;
    using Microsoft.TeamFoundation.VersionControl.Client;
    using My.CodePlex.TFSExplorer.Resources;
    using My.CodePlex.TFSExplorer.TeamFoundation;

    /// <summary>
    /// Interaction logic for PendingChangesControl.xaml
    /// </summary>
    public partial class PendingChangesControl : UserControl, IExplorerControl
    {
        #region Fields

        /// <summary>
        /// Thread that populates the pending changes
        /// </summary>
        private Thread populatePendingChangesThread;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the PendingChangesControl class
        /// </summary>
        public PendingChangesControl()
        {
            InitializeComponent();

            this.ControlName = Resource.PendingChangesControlName;
            this.Header = Resource.PendingChangesTabItemHeader;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets  the control name
        /// </summary>
        public string ControlName { get; set; }

        /// <summary>
        /// Gets or sets the control tab item header
        /// </summary>
        public string Header { get; set; }

        /// <summary>
        /// Gets or sets the TFS context
        /// </summary>
        public TeamFoundationContext TeamFoundationContext { get; set; }

        #endregion

        #region Public methods

        /// <summary>
        /// Populate the pending changes listview
        /// </summary>
        /// <param name="tfsContext">The TFS context</param>
        public void Populate(TeamFoundationContext tfsContext)
        {
            this.TeamFoundationContext = tfsContext;

            // Set up the thread to populate the source tree view
            this.populatePendingChangesThread = new Thread(this.PopulatePendingChangesView);
            this.populatePendingChangesThread.SetApartmentState(ApartmentState.STA);
            this.populatePendingChangesThread.Start(TeamFoundationContext.CurrentProject.ServerItem);
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Populate the pending changes listview
        /// </summary>
        /// <param name="data">The name of the topmost folder</param>
        private void PopulatePendingChangesView(object data)
        {
            ItemSpec[] itemSpecs = new ItemSpec[1];
            itemSpecs[0] = new ItemSpec(TeamFoundationContext.CurrentProject.ServerItem, RecursionType.Full);
            PendingSet[] pendingSetArray = TeamFoundationContext.VersionControlServer.QueryPendingSets(itemSpecs, null, TeamFoundationContext.CurrentDisplayUser);

            ObservableCollection<PendingChangeItem> obsCollection = new ObservableCollection<PendingChangeItem>();

            this.PendingChangesView.Dispatcher.BeginInvoke((Action)(() =>
            {
                foreach (PendingSet pendingSet in pendingSetArray)
                {
                    foreach (PendingChange pendingChange in pendingSet.PendingChanges)
                    {
                        PendingChangeItem fileItem = new PendingChangeItem();
                        fileItem.FileName = Path.GetFileName(pendingChange.ServerItem);
                        fileItem.ServerItem = pendingChange.ServerItem;

                        fileItem.ImgSource = FileIconRepository.GetFileIconImage(Path.GetExtension(fileItem.FileName)).ToImageSource();
                        fileItem.ChangeTypeName = pendingChange.ChangeTypeName;
                        fileItem.CreationDate = pendingChange.CreationDate.ToShortDateString() + " " + pendingChange.CreationDate.ToLongTimeString();
                        fileItem.LocalItem = pendingChange.LocalItem;

                        obsCollection.Add(fileItem);
                    }
                }

                this.PendingChangesView.ItemsSource = obsCollection;
            }));
        }

        /// <summary>
        /// Handle the checkin button click and check files into TFS
        /// </summary>
        /// <param name="sender">The sender object</param>
        /// <param name="e">The event arguments</param>
        private void CheckinClick(object sender, System.Windows.RoutedEventArgs e)
        {
            List<string> pending = new List<string>();

            // Get all the checkboxes and check them in
            foreach (var pend in this.PendingChangesView.ItemsSource)
            {
                PendingChangeItem pendingChangeItem = pend as PendingChangeItem;
                if (pendingChangeItem.IsSelected)
                {
                    pending.Add(pendingChangeItem.ServerItem);
                }
            }

            PendingChange[] allPendingChange = TeamFoundationContext.Workspace.GetPendingChanges();

            PendingChange[] pendingChange = TeamFoundationContext.Workspace.GetPendingChanges(pending.ToArray());
            CheckinEvaluationResult result = TeamFoundationContext.Workspace.EvaluateCheckin(CheckinEvaluationOptions.All, allPendingChange, pendingChange, string.Empty, null, null);
            if (result.Conflicts.Length != 0)
            {
                StringBuilder sb = new StringBuilder();
 
                foreach (CheckinConflict ck in result.Conflicts)
                {
                    sb.Append(ck.ServerItem + " : " + ck.Message + " : " + ck.Resolvable + Environment.NewLine);
                }

                System.Windows.Forms.MessageBox.Show(sb.ToString());
            }

            try
            {
                int changesetNumber = TeamFoundationContext.Workspace.CheckIn(pendingChange, this.ShelvesetComment.Text);
            }
            catch (CheckinException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message, Resource.ProductNameLong, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }

            // Refresh the pending changes view
            this.Populate(this.TeamFoundationContext);
        }

        /// <summary>
        /// Shelve the pending changes
        /// </summary>
        /// <param name="sender">The sender object</param>
        /// <param name="e">The event arguments</param>
        private void ShelveClick(object sender, System.Windows.RoutedEventArgs e)
        {
            List<string> pending = new List<string>();

            // Get all the checkboxes and check them in
            foreach (var pend in this.PendingChangesView.ItemsSource)
            {
                PendingChangeItem pendingChangeItem = pend as PendingChangeItem;
                if (pendingChangeItem.IsSelected)
                {
                    pending.Add(pendingChangeItem.ServerItem);
                }
            }

            try
            {
                Shelveset shelveset = new Shelveset(TeamFoundationContext.VersionControlServer, this.ShelvesetName.Text, TeamFoundationContext.CurrentDisplayUser);
                shelveset.Comment = this.ShelvesetComment.Text;

                PendingChange[] pendingChange = TeamFoundationContext.Workspace.GetPendingChanges(pending.ToArray());
                TeamFoundationContext.Workspace.Shelve(shelveset, pendingChange, ShelvingOptions.None);
            }
            catch (VersionControlException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message, Resource.ProductNameLong, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Refresh the pending changes view
        /// </summary>
        /// <param name="sender">The sender object</param>
        /// <param name="e">The event arguments</param>
        private void RefreshClick(object sender, System.Windows.RoutedEventArgs e)
        {
            // Refresh the pending changes view
            this.Populate(this.TeamFoundationContext);
        }

        #endregion

        /// <summary>
        /// Undo the pending change
        /// </summary>
        /// <param name="sender">The sender object</param>
        /// <param name="e">The event arguments</param>
        private void UndoClick(object sender, System.Windows.RoutedEventArgs e)
        {
            List<string> pending = new List<string>();

            // Get all the checkboxes and check them in
            foreach (var pend in this.PendingChangesView.ItemsSource)
            {
                PendingChangeItem pendingChangeItem = pend as PendingChangeItem;
                if (pendingChangeItem.IsSelected)
                {
                    pending.Add(pendingChangeItem.ServerItem);
                }
            }

            try
            {
                PendingChange[] pendingChange = TeamFoundationContext.Workspace.GetPendingChanges(pending.ToArray());
                TeamFoundationContext.Workspace.Undo(pendingChange);
            }
            catch (VersionControlException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message, Resource.ProductNameLong, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }

            // Refresh the pending changes view
            this.Populate(this.TeamFoundationContext);
        }
    }  
}
